package net.lucode.hackware.magicindicator.buildins.commonnavigator.titles;

import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * 类似今日头条切换效果的指示器标题
 *
 * @since 2020-09-29
 */
public class ClipPagerTitleView extends Component implements IMeasurablePagerTitleView,
        Component.DrawTask, Component.EstimateSizeListener {
    private String mText;
    private int mTextColor;
    private int mClipColor;
    private boolean mIsLeftToRight = false;
    private float mClipPercent;

    private Paint mPaint;
    private Rect mTextBounds = new Rect();

    /**
     * ClipPagerTitleView
     *
     * @param context context
     */
    public ClipPagerTitleView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        int textSize = UIUtil.fp2px(context, 16);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(textSize);
        int padding = UIUtil.vp2px(context, 5);
        setPadding(padding, 0, padding, 0);
        addDrawTask(this);
        setEstimateSizeListener(this);
    }

    @Override
    public boolean onEstimateSize(int widthEstimateSpec, int heightEstimateSpec) {
        measureTextBounds();
        int width = measureWidth(widthEstimateSpec);
        int height = measureHeight(heightEstimateSpec);
        setEstimatedSize(Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED));
        return true;
    }

    private int measureWidth(int widthEstimateSpec) {
        int mode = EstimateSpec.getMode(widthEstimateSpec);
        int size = EstimateSpec.getSize(widthEstimateSpec);
        int result = size;
        switch (mode) {
            case EstimateSpec.NOT_EXCEED:
                int width = mTextBounds.getWidth() + getPaddingLeft() + getPaddingRight();
                result = Math.min(width, size);
                break;
            case EstimateSpec.UNCONSTRAINT:
                result = mTextBounds.getWidth() + getPaddingLeft() + getPaddingRight();
                break;
            default:
                break;
        }
        return result;
    }

    private int measureHeight(int heightEstimateSpec) {
        int mode = EstimateSpec.getMode(heightEstimateSpec);
        int size = EstimateSpec.getSize(heightEstimateSpec);
        int result = size;
        switch (mode) {
            case EstimateSpec.NOT_EXCEED:
                int height = mTextBounds.getHeight() + getPaddingTop() + getPaddingBottom();
                result = Math.min(height, size);
                break;
            case EstimateSpec.UNCONSTRAINT:
                result = mTextBounds.getHeight() + getPaddingTop() + getPaddingBottom();
                break;
            default:
                break;
        }
        return result;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int widthX = (getWidth() - mTextBounds.getWidth()) / 2;
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        int heightY = (int) ((getHeight() - fontMetrics.bottom - fontMetrics.top) / 2);

        // 画底层
        mPaint.setColor(new Color(mTextColor));
        canvas.drawText(mPaint, mText, widthX, heightY);

        // 画clip层
        RectFloat rectFloat;
        if (mIsLeftToRight) {
            rectFloat = new RectFloat(0, 0, getWidth() * mClipPercent, getHeight());
        } else {
            rectFloat = new RectFloat(getWidth() * (1 - mClipPercent), 0, getWidth(), getHeight());
        }

        // 保存当前图层并创建指定大小的图层，之后的操作都在新图层上
        int layerId = canvas.saveLayer(rectFloat, mPaint);
        canvas.clipRect(rectFloat);
        mPaint.setColor(new Color(mClipColor));
        canvas.drawText(mPaint, mText, widthX, heightY);

        // 恢复到原图层
        canvas.restoreToCount(layerId);
    }

    @Override
    public void onSelected(int index, int totalCount) {
    }

    @Override
    public void onDeselected(int index, int totalCount) {
    }

    @Override
    public void onLeave(int index, int totalCount, float leavePercent, boolean isLeftToRight) {
        mIsLeftToRight = !isLeftToRight;
        mClipPercent = 1.0f - leavePercent;
        invalidate();
    }

    @Override
    public void onEnter(int index, int totalCount, float enterPercent, boolean isLeftToRight) {
        mIsLeftToRight = isLeftToRight;
        mClipPercent = enterPercent;
        invalidate();
    }

    private void measureTextBounds() {
        mTextBounds = mPaint.getTextBounds(mText);
    }

    /**
     * getText
     *
     * @return mText
     */
    public String getText() {
        return mText;
    }

    /**
     * setText
     *
     * @param text text
     */
    public void setText(String text) {
        mText = text;
        postLayout();
    }

    /**
     * getTextSize
     *
     * @return Paint TextSize
     */
    public int getTextSize() {
        return mPaint.getTextSize();
    }

    /**
     * setTextSize
     *
     * @param textSize textSize
     */
    public void setTextSize(float textSize) {
        mPaint.setTextSize((int) textSize);
        postLayout();
    }

    /**
     * setTextColor
     *
     * @param textColor textColor
     */
    public void setTextColor(int textColor) {
        mTextColor = textColor;
        invalidate();
    }

    /**
     * getClipColor
     *
     * @return mClipColor
     */
    public int getClipColor() {
        return mClipColor;
    }

    /**
     * setClipColor
     *
     * @param clipColor clipColor
     */
    public void setClipColor(int clipColor) {
        mClipColor = clipColor;
        invalidate();
    }

    @Override
    public int getContentLeft() {
        int contentWidth = mTextBounds.getWidth();
        return getLeft() + getWidth() / 2 - contentWidth / 2;
    }

    @Override
    public int getContentTop() {
        Paint.FontMetrics metrics = mPaint.getFontMetrics();
        float contentHeight = metrics.bottom - metrics.top;
        return getHeight() / 2 - (int) contentHeight / 2;
    }

    @Override
    public int getContentRight() {
        int contentWidth = mTextBounds.getWidth();
        return getLeft() + getWidth() / 2 + contentWidth / 2;
    }

    @Override
    public int getContentBottom() {
        Paint.FontMetrics metrics = mPaint.getFontMetrics();
        float contentHeight = metrics.bottom - metrics.top;
        return getHeight() / 2 + (int) contentHeight / 2;
    }
}
